#include "mysql_handle.h"

#include <cstddef>
#include <mysql/mysql.h>
#include <stdexcept>

MySQLHandle::MySQLHandle(
    const std::string &host, uint16_t port, const std::string &username, const std::string &password, const std::string &database)
{
    mysql_handle_ = mysql_init(NULL);
    if (!mysql_real_connect(mysql_handle_, host.c_str(), username.c_str(), password.c_str(), database.c_str(), port, nullptr, 0)) {
        throw std::runtime_error(mysql_error(mysql_handle_));
    }

    if (mysql_set_character_set(mysql_handle_, "utf8") != 0) {
        throw std::runtime_error(mysql_error(mysql_handle_));
    }
}

MySQLHandle::~MySQLHandle()
{
    if (mysql_handle_)
        mysql_close(mysql_handle_);
}

void MySQLHandle::Create(const std::string &sql)
{
    if (mysql_query(mysql_handle_, sql.c_str()) != 0) {
        throw std::runtime_error(mysql_error(mysql_handle_));
    }
}

void MySQLHandle::Drop(const std::string &sql)
{
    if (mysql_query(mysql_handle_, sql.c_str()) != 0) {
        throw std::runtime_error(mysql_error(mysql_handle_));
    }
}

uint64_t MySQLHandle::Insert(const std::string &sql)
{
    if (mysql_query(mysql_handle_, sql.c_str()) != 0) {
        throw std::runtime_error(mysql_error(mysql_handle_));
    }
    return mysql_insert_id(mysql_handle_);
}

void MySQLHandle::InsertList(const std::string &sql)
{
    if (mysql_query(mysql_handle_, sql.c_str()) != 0) {
        throw std::runtime_error(mysql_error(mysql_handle_));
    }
}

uint64_t MySQLHandle::Update(const std::string &sql)
{
    if (mysql_query(mysql_handle_, sql.c_str()) != 0) {
        throw std::runtime_error(mysql_error(mysql_handle_));
    }
    return mysql_insert_id(mysql_handle_);
}

uint64_t MySQLHandle::Remove(const std::string &sql)
{
    if (mysql_query(mysql_handle_, sql.c_str()) != 0) {
        throw std::runtime_error(mysql_error(mysql_handle_));
    }
    return mysql_insert_id(mysql_handle_);
}

MySQLResult MySQLHandle::Select(const std::string &sql)
{
    if (mysql_real_query(mysql_handle_, sql.c_str(), sql.size()) != 0) {
        throw std::runtime_error(mysql_error(mysql_handle_));
    }
    MYSQL_RES *res = mysql_store_result(mysql_handle_);
    if (!res) {
        throw std::runtime_error(mysql_error(mysql_handle_));
    }
    return MySQLResult(res);
}
